package com.dnndo.common.utils;

import com.alibaba.fastjson2.JSON;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dnndo.common.exception.CustomExceptions;
import jakarta.annotation.PostConstruct;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * 阿里云短信工具类
 */
@Component
@Log4j2
public class SmsUtil {
    @Value("${aliyun.sms.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.sms.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyun.sms.signName}")
    private String signName;
    @Value("${aliyun.sms.templateCode}")
    private String templateCode;

    private Client smsClient;

    @PostConstruct
    private void initClient() {
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        try {
            this.smsClient = new Client(config); // 仅初始化一次
            log.info("短信客户端初始化成功");
        } catch (Exception e) {
            log.error("短信客户端初始化失败:{}", e.getMessage());
        }
    }


    /**
     * 发送短信
     * @param phone 手机号
     * @param code 短信验证码
     */
    @Async("smsThreadPoolTaskExecutor")
    public void sendSms(String phone,String code) {
        try {
            SendSmsRequest sendSmsRequest = new SendSmsRequest()
                    .setTemplateParam("{\"code\":\""+code+"\"}")
                    .setPhoneNumbers(phone)
                    .setSignName(signName)
                    .setTemplateCode(templateCode);
            RuntimeOptions runtime = new RuntimeOptions();
            SendSmsResponse sendSmsResponse = smsClient.sendSmsWithOptions(sendSmsRequest, runtime);
            //输出日志
            checkErrorCode(sendSmsResponse, phone, code);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            log.error("短信发送失败(系统异常):{},Recommend:{}", error.getMessage(), error.getData().get("Recommend"));
            Common.assertAsString(error.message);
        }
    }
    /**
     * 阿里云短信错误码判断
     * @param sendSmsResponse 发送短信返回对象
     * @param phone 手机号
     * @param smsCode 短信验证码
     */
    private void checkErrorCode(SendSmsResponse sendSmsResponse,String phone,String smsCode) {
        SendSmsResponseBody body = sendSmsResponse.getBody();
        String code = body.getCode();
        switch (code) {
            case "OK":
                log.info("短信发送成功,手机号:{} 验证码:{} 返回信息:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "isv.DAY_LIMIT_CONTROL":
                log.error("短信发送失败,手机号:{} 验证码:{} 触发日发送限额:{}", phone, smsCode, JSON.toJSONString(body));
            case "isv.MONTH_LIMIT_CONTROL":
                log.error("短信发送失败,手机号:{} 验证码:{} 触发月发送限额:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "isv.OUT_OF_SERVICE":
                log.error("短信发送失败,手机号:{} 验证码:{} 业务停机:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "isv.SYSTEM_ERROR":
                log.error("短信发送失败,手机号:{} 验证码:{} 系统出现错误，请重新调用:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "isv.MOBILE_NUMBER_ILLEGAL":
                log.error("短信发送失败,手机号:{} 验证码:{} 手机号码格式错误:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "isv.BUSINESS_LIMIT_CONTROL":
                log.error("短信发送失败,手机号:{} 验证码:{} 触发云通信流控限制:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "isv.BLACK_KEY_CONTROL_LIMIT":
                log.error("短信发送失败,手机号:{} 验证码:{} 黑名单管控:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "isv.AMOUNT_NOT_ENOUGH":
                log.error("短信发送失败,手机号:{} 验证码:{} 账户余额不足:{}", phone, smsCode, JSON.toJSONString(body));
                break;
            case "MOBILE_NOT_ON_SERVICE":
                log.error("短信发送失败,手机号:{} 验证码:{} 停机、空号、暂停服务、关机、不在服务区:{}", phone, smsCode, JSON.toJSONString(body));
            case "MOBILE_SEND_LIMIT":
                log.error("短信发送失败,手机号:{} 验证码:{} 单个号码日、月发送上限，流控超限，频繁发送超限:{}", phone, smsCode, JSON.toJSONString(body));
            case "MOBILE_ACCOUNT_ABNORMAL":
                log.error("短信发送失败,手机号:{} 验证码:{} 用户账户异常、携号转网、欠费等:{}", phone, smsCode, JSON.toJSONString(body));
            case "INVALID_NUMBER":
                log.error("短信发送失败,手机号:{} 验证码:{} 号码状态异常:{}", phone, smsCode, JSON.toJSONString(body));
            default:
                log.error("短信发送失败,手机号:{} 验证码:{} 未知错误:{}", phone, smsCode, JSON.toJSONString(body));
        }
    }
}
